package vip.afeng.screen;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.BinaryMessage;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.RemoteEndpoint;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 前后端交互的类实现消息的接收推送(自己发送给所有人(不包括自己))
 *
 * @ServerEndpoint(value = "/test/oneToMany") 前端通过此URI 和后端交互，建立连接
 */
@Slf4j
@ServerEndpoint(value = "/test/oneToMany")
@Component
public class OneToManyWebSocket {

    /**
     * 记录当前在线连接数
     */
    private static AtomicInteger onlineCount = new AtomicInteger(0);

    /**
     * 存放所有在线的客户端
     */
    private static Map<String, Session> clients = new ConcurrentHashMap<>();

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) throws IOException {
        onlineCount.incrementAndGet(); // 在线数加1
        clients.put(session.getId(), session);
        log.info("有新连接加入 sessionId：{}，当前在线人数为：{}", session.getId(), onlineCount.get());
    }

    Random random = new Random();
    String[] imgs = {
            "",""
    };

    GuiCamera guiCamera = new GuiCamera();
    @Scheduled(fixedRate = 100)
    public void  send() throws IOException {
//        System.out.println("定时任务发送");
        byte[] snapshot = guiCamera.snapshot();

        // TODO 并发问题, 数据压缩
        synchronized(this){
            for (Map.Entry<String, Session> sessionEntry : clients.entrySet()) {
                Session toSession = sessionEntry.getValue();

//            FileInputStream fs = new FileInputStream(imgs[random.nextInt(imgs.length)]); // [0,imgs.length)
//            byte[] snapshot = guiCamera.snapshot();
//获取指定文件的长度并用它来创建一个可以存放内容的字节数组
//            在传输中，图片是不能直接传的，因此需要把图片变为字节数组，然后传输比较方便；只需要一般输出流的write方法即可；
//
//            而字节数组变成BufferedImage能够还原图像；
//            byte[] content = new byte[fs.available()];
//            System.out.println("content.length = " + content.length);
                //将图片内容读入到字节数组
//            fs.read(content);

                //使用刚才的字节数组创建ByteBuffer对象

                ByteBuffer byteBuffer = ByteBuffer.wrap(snapshot); // 堆, 一次性出

//                RemoteEndpoint.Basic basic = toSession.getBasicRemote();
//                //发送byteBuffer对象到客户端
//                basic.sendBinary(byteBuffer);

                toSession.getBasicRemote().sendBinary(byteBuffer);

//            toSession.getAsyncRemote().sendBinary(byteBuffer);


//            toSession.getAsyncRemote().sendText("message");
                // 发送图片
//            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//            byteBuffer.put((byte) 111);

//            fs.close();

//            BinaryMessage binaryMessage = new BinaryMessage();
//            toSession.getBasicRemote().
//            toSession.getAsyncRemote().sendBinary(byteBuffer);

                // 排除掉自己
//            if (!fromSession.getId().equals(toSession.getId())) {
//                log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), "message");
//                toSession.getAsyncRemote().sendText("message");
//            }
            }
        }

    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        onlineCount.decrementAndGet(); // 在线数减1
        synchronized (this) {
            clients.remove(session.getId());
        }
        log.info("有一连接关闭：{}，当前在线人数为：{}", session.getId(), onlineCount.get());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("服务端收到客户端[{}]的消息:{}", session.getId(), message);
        this.sendMessage(message, session);
    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }

    /**
     * 群发消息
     *
     * @param message 消息内容
     */
    private void sendMessage(String message, Session fromSession) {
        for (Map.Entry<String, Session> sessionEntry : clients.entrySet()) {
            Session toSession = sessionEntry.getValue();
            // 排除掉自己
            if (!fromSession.getId().equals(toSession.getId())) {
                log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
                toSession.getAsyncRemote().sendText(message);
            }
        }
    }
}